Make `cargo update` more conservative.
authorAlex Crichton <alex@alexcrichton.com>
Sun, 21 Sep 2014 21:27:30 +0000 (14:27 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Sun, 21 Sep 2014 21:27:30 +0000 (14:27 -0700)
As described in #613, this commit switches the semantics of `cargo update foo`
to updating *only* `foo`, not any of its dependencies. A new flag,
`--aggressive` was added to restore the old behavior.

The behavior of attempting to only unlock `foo`, and then if resolve fails
unlock all dependencies of `foo` is unimplemented as it's not super relevant
right now when the majority of dependencies are git dependencies and resolution
cannot fail for version-related reasons.

Closes #613

src/bin/update.rs
src/cargo/ops/cargo_generate_lockfile.rs
tests/test_cargo_compile_git_deps.rs

index 705832cc06f2b5a298d507dfbd19b51e8ea1fb05..79bd754dea34483ef4e132502824e5f3171eac08 100644 (file)
@@ -14,6 +14,7 @@ Usage:
 
 Options:
     -h, --help              Print this message
+    --aggressive            Force updating all dependencies of <name> as well
     --manifest-path PATH    Path to the manifest to compile
     -v, --verbose           Use verbose output
 
@@ -21,9 +22,10 @@ This command requires that a `Cargo.lock` already exists as generated by
 `cargo build` or related commands.
 
 If <name> is specified, then a conservative update of the lockfile will be
-performed. This means that only the dependency <name> (and all of its transitive
-dependencies) will be updated. All other dependencies will remain locked at
-their currently recorded versions.
+performed. This means that only the dependency <name> will be updated. Its
+transitive dependencies will be updated only if <name> cannot be updated without
+updating dependencies.  All other dependencies will remain locked at their
+currently recorded versions.
 
 If <name> is not specified, then all dependencies will be re-resolved and
 updated.
@@ -34,7 +36,7 @@ pub fn execute(options: Options, shell: &mut MultiShell) -> CliResult<Option<()>
     shell.set_verbose(options.flag_verbose);
     let root = try!(find_root_manifest_for_cwd(options.flag_manifest_path));
 
-    ops::update_lockfile(&root, shell, options.arg_name)
+    ops::update_lockfile(&root, shell, options.arg_name, options.flag_aggressive)
         .map(|_| None).map_err(|err| CliError::from_boxed(err, 101))
 }
 
index 44b281289df7e99b338a2c10ab907c241093f5a2..7e6327d56a1748c71ef8f91921029c2a2203aa3f 100644 (file)
@@ -35,7 +35,8 @@ pub fn generate_lockfile(manifest_path: &Path,
 
 pub fn update_lockfile(manifest_path: &Path,
                        shell: &mut MultiShell,
-                       to_update: Option<String>) -> CargoResult<()> {
+                       to_update: Option<String>,
+                       aggressive: bool) -> CargoResult<()> {
     let mut source = try!(PathSource::for_path(&manifest_path.dir_path()));
     try!(source.update());
     let package = try!(source.get_root_package());
@@ -54,7 +55,11 @@ pub fn update_lockfile(manifest_path: &Path,
         Some(name) => {
             let mut to_avoid = HashSet::new();
             for dep in resolve.iter().filter(|d| d.get_name() == name.as_slice()) {
-                fill_with_deps(&resolve, dep, &mut to_avoid);
+                if aggressive {
+                    fill_with_deps(&resolve, dep, &mut to_avoid);
+                } else {
+                    to_avoid.insert(dep);
+                }
             }
             resolve.iter().filter(|pkgid| !to_avoid.contains(pkgid))
                    .map(|pkgid| pkgid.get_source_id().clone()).collect()
index 181de8f9b698f804a793caa953e9f7d1f308caad..941a8905257b5a9480f39a1e330d01511f78b7f5 100644 (file)
@@ -687,6 +687,9 @@ test!(update_with_shared_deps {
     timer::sleep(Duration::milliseconds(1000));
 
     assert_that(p.process(cargo_dir().join("cargo")).arg("update").arg("dep1"),
+                execs().with_stdout(""));
+    assert_that(p.process(cargo_dir().join("cargo")).arg("update").arg("dep1")
+                 .arg("--aggressive"),
                 execs().with_stdout(format!("{} git repository `{}`",
                                             UPDATING,
                                             git_project.url())));